﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Castle.Windsor;
using Microsoft.Win32;
using SuppKids.Core;
using SuppKids.Core.Domain;
using SuppKids.Core.Reporting;
using SuppKids.Core.Reporting.Data;
using SuppKids.Core.Services;
using SuppKids.Resources;
using SuppKids.ViewModels;

namespace SuppKids
{
	public partial class Sklad : BaseWindow
	{
		private readonly ReportGeneratorFactory reportGeneratorFactory;
		private readonly ProductAtStorageService productAtStorageService;
		private readonly ProductService productService;

		public ProductAtStorageViewModel ViewModel
		{
			get
			{
				return (ProductAtStorageViewModel)this.DataContext;
			}
			set
			{
				this.DataContext = value;
			}
		}

		public Sklad(IWindsorContainer container, LicenseService licenseService, ReportGeneratorFactory reportGeneratorFactory, ProductAtStorageService productAtStorageService, ProductService productService)
			: base(container, licenseService)
		{
			this.reportGeneratorFactory = reportGeneratorFactory;
			this.productAtStorageService = productAtStorageService;
			this.productService = productService;

			this.ViewModel = new ProductAtStorageViewModel();
            this.EnableDateFilter = new CheckBox();
            this.EnableProductFilter = new CheckBox();
			InitializeComponent();

			this.ProductsList.ItemsSource = productService.GetAll();
			this.ProductsList.SelectedValuePath = Lambda.Property<Product>(a => a.Id);
			this.ProductsList.DisplayMemberPath = Lambda.Property<Product>(a => a.Name);

            //product filter
            this.ProductsListFilter.ItemsSource = productService.GetAll();
            this.ProductsListFilter.SelectedValuePath = Lambda.Property<Product>(a => a.Id);
            this.ProductsListFilter.DisplayMemberPath = Lambda.Property<Product>(a => a.Name);
		}

		private void FilterChanged(object sender, SelectionChangedEventArgs e) // was ProductChanged
		{
            bool? enabled;
            if (sender is ComboBox)
            {
                enabled = this.EnableProductFilter.IsChecked;
                
                if (sender.Equals(this.ProductsListFilter))
                {
                    this.ProductsList.SelectedIndex = this.ProductsListFilter.SelectedIndex;
                }
                
            }
            else //if(sender is DatePicker)
            {
                enabled = this.EnableDateFilter.IsChecked;
                
                if (sender.Equals(this.DeliveryDateFilter))
                {
                    this.DeliveryDate.SelectedDate = this.DeliveryDateFilter.SelectedDate;
                }
                
            }
            /*
            if ((bool)enabled)
            {
                this.UpdateResultGrid();
            }
            */
 
		}

		public IEnumerable<ProductAtStorageViewModel> ProductsAtStorage
		{
			get
			{
                if ( this.DeliveryDateFilter.DisplayDate != null)
				{
                    if (this.SelectedProductFilter != null) { 
					    var items = this.productAtStorageService
                            .GetAll(a => (
                                           (this.EnableProductFilter.IsChecked == false || a.Product.Id == this.SelectedProductFilter.Id)
                                        && (this.EnableDateFilter.IsChecked==false || a.DeliveryDate == this.DeliveryDateFilter.DisplayDate)
                                         )
                                    )
                            .OrderBy(a=>a.DeliveryDate).ToArray();
                        var balance = 0d;
                        foreach (var item in items)
                        {
                            balance += item.Balance;
                            yield return new ProductAtStorageViewModel(item, balance);
                        }
                    }
                    else
                    {
                        var items = this.productAtStorageService
                            .GetAll(a => (this.EnableDateFilter.IsChecked == false || a.DeliveryDate == this.DeliveryDateFilter.DisplayDate)                                        
                                    )
                            .OrderBy(a => a.DeliveryDate).ToArray();
                        var balance = 0d;
                        foreach (var item in items)
                        {
                            balance += item.Balance;
                            yield return new ProductAtStorageViewModel(item, balance);
                        }
                    }

				}
			}
		} 

		private void SaveButtonClick(object sender, RoutedEventArgs e)
		{
			if (this.ViewModel.Product == null && this.ViewModel.ProductAtStorage.IsTransient)
			{
				this.ViewModel.Product = this.SelectedProduct;
			}

			if (this.ViewModel.AllFieldsIsNotEmpty)
			{
				this.productAtStorageService.RegisterSave(this.ViewModel.ProductAtStorage, true);
				this.ViewModel = new ProductAtStorageViewModel();
				this.UpdateResultGrid();
			}
		}

		private void ResultGridSelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			this.ViewModel = this.ResultGrid.SelectedItem as ProductAtStorageViewModel ?? new ProductAtStorageViewModel();
		}

		private void UpdateResultGrid()
		{
            this.ResultGrid.GetBindingExpression(DataGrid.ItemsSourceProperty).UpdateTarget();
		}

		private Product SelectedProduct
		{
			get
			{
				return this.ProductsList.SelectedItem as Product;
			}
		}
        private Product SelectedProductFilter
        {
            get
            {
                return this.ProductsListFilter.SelectedItem as Product;
            }
        }
		private void DailyReportClick(object sender, RoutedEventArgs e)
		{
            /*
			if (this.SelectedProduct == null)
			{
				MessageBox.Show(Messages.ProductIsNotSelected);
				return;
			}
            */
            var startDate = this.DailyReportDate.SelectedDate ?? DateTime.Now; // DeliveryDate
			var endDate = startDate.AddDays(1);

			var saveFile = new SaveFileDialog
			{
                FileName = "Отчёт за " + startDate.Day.ToString() + "." + startDate.Month.ToString() + "." + startDate.Year.ToString() + ".xlsx",
				DefaultExt = ".xlsx",
				Filter = "Excel files (.xlsx)|*.xlsx"
			};

			if (saveFile.ShowDialog() == true)
			{
				Stream stream = null;
				try
				{
					stream = saveFile.OpenFile();
					var reportGenerator = this.reportGeneratorFactory.GetReportGenerator(ReportType.SkladDaily, ReportFormat.Excel);
					var products =
						productAtStorageService.GetAll(
							a =>
								a.DeliveryDate >= startDate &&
								a.DeliveryDate < endDate).OrderBy(a => a.Product.Name).ThenBy(a => a.DeliveryDate);
                    reportGenerator.GenerateReport(new SkladDailyReportData(products, startDate), stream);
                    /* was this
                    var products =
                        productAtStorageService.GetAll(
                            a =>
                                a.Product.Id == this.SelectedProduct.Id && a.DeliveryDate >= startDate &&
                                a.DeliveryDate < endDate).OrderBy(a => a.Product.Name).ThenBy(a => a.DeliveryDate);
                    reportGenerator.GenerateReport(new SkladDailyReportData(products), stream);
                    */
				}
				catch (Exception)
				{
					MessageBox.Show(Messages.SaveFileError);
				}
				finally
				{
					if (stream != null)
					{
						stream.Dispose();
					}
				}
			}
		}

		private void MonthlyReportClick(object sender, RoutedEventArgs e)
		{
			var now = DateTime.Now;
			var startDate = new DateTime(now.Year, now.Month, 1).AddMonths(-1);
			var endDate = new DateTime(now.Year, now.Month, 1).AddTicks(-1);

			var saveFile = new SaveFileDialog
			{
				FileName = "Отчёт за предыдущий месяц.xlsx",
				DefaultExt = ".xlsx",
				Filter = "Excel files (.xlsx)|*.xlsx"
			};

			if (saveFile.ShowDialog() == true)
			{
				Stream stream = null;
				try
				{
					stream = saveFile.OpenFile();
					var reportGenerator = this.reportGeneratorFactory.GetReportGenerator(ReportType.SkladMonthly, ReportFormat.Excel);
					var products = productService.GetAll().OrderBy(a => a.Name);
					var productsAtStorage = productAtStorageService.GetAll(a => a.DeliveryDate >= startDate && a.DeliveryDate <= endDate).OrderBy(a => a.Product.Name).ThenBy(a => a.DeliveryDate);
					reportGenerator.GenerateReport(new SkladMonthlyReportData(products, productsAtStorage, startDate, endDate), stream);
				}
				catch (Exception)
				{
					MessageBox.Show(Messages.SaveFileError);
				}
				finally
				{
					if (stream != null)
					{
						stream.Dispose();
					}
				}
			}
		}

		private void MoveProductsReportClick(object sender, RoutedEventArgs e)
		{
			var saveFile = new SaveFileDialog
			{
				FileName = "Перемешение продуктов.xlsx",
				DefaultExt = ".xlsx",
				Filter = "Excel files (.xlsx)|*.xlsx"
			};

			if (saveFile.ShowDialog() == true)
			{
				Stream stream = null;
				try
				{
					stream = saveFile.OpenFile();
					var reportGenerator = this.reportGeneratorFactory.GetReportGenerator(ReportType.MoveProducts, ReportFormat.Excel);
					var products = productService.GetAll();
					reportGenerator.GenerateReport(new MoveProductsReportData(products), stream);
				}
				catch (Exception)
				{
					MessageBox.Show(Messages.SaveFileError);
				}
				finally
				{
					if (stream != null)
					{
						stream.Dispose();
					}
				}
			}
		}
        private void AllProductsReportClick(object sender, RoutedEventArgs e)
        {
            var saveFile = new SaveFileDialog
            {
                FileName = "Все продукты на складе.xlsx",
                DefaultExt = ".xlsx",
                Filter = "Excel files (.xlsx)|*.xlsx"
            };

            if (saveFile.ShowDialog() == true)
            {
                Stream stream = null;
                try
                {
                    stream = saveFile.OpenFile();
                    var reportGenerator = this.reportGeneratorFactory.GetReportGenerator(ReportType.AllProducts, ReportFormat.Excel);
                    var products =
                        productAtStorageService.GetAll().OrderBy(a => a.Product.Name).ThenBy(a => a.DeliveryDate);
                    reportGenerator.GenerateReport(new AllProductsReportData(products), stream);
                }
                catch (Exception)
                {
                    MessageBox.Show(Messages.SaveFileError);
                }
                finally
                {
                    if (stream != null)
                    {
                        stream.Dispose();
                    }
                }
            }
        }
		private void RemoveButtonClick(object sender, RoutedEventArgs e)
		{
			if (!this.ViewModel.ProductAtStorage.IsTransient && MessageBox.Show(Messages.DeleteProductAtStorageConfirmation, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
			{
				var itemToRemove = this.ViewModel.ProductAtStorage;
				this.productAtStorageService.RegisterDelete(itemToRemove, true);
				UpdateResultGrid();
			}
		}

        private void FilterButtonClick(object sender, RoutedEventArgs e)
        {
            this.UpdateResultGrid();
        }
	}
}
